package com.fg.cloud.manager.service.agency.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.fg.cloud.common.NumberUtil;
import com.fg.cloud.common.PageUtils;
import com.fg.cloud.common.ServiceException;
import com.fg.cloud.common.StatusCode;
import com.fg.cloud.common.finals.AgencyAccount;
import com.fg.cloud.common.finals.AgencyBill;
import com.fg.cloud.common.finals.PayStatus;
import com.fg.cloud.common.shiro.UserUtils;
import com.fg.cloud.manager.entry.BaseEntity;
import com.fg.cloud.manager.entry.agency.AgencyAccountEntity;
import com.fg.cloud.manager.entry.agency.AgencyBillEntity;
import com.fg.cloud.manager.entry.agency.AgencyBillWeChatEntity;
import com.fg.cloud.manager.entry.agency.vo.AgencyBillVo;
import com.fg.cloud.manager.entry.agency.vo.AgencyUserVo;
import com.fg.cloud.manager.entry.factory.vo.FactoryUserVo;
import com.fg.cloud.manager.entry.order.OrderInfoEntity;
import com.fg.cloud.manager.entry.order.OrderPaymentEntity;
import com.fg.cloud.manager.mapper.BaseMapper;
import com.fg.cloud.manager.mapper.agency.AgencyAccountMapper;
import com.fg.cloud.manager.mapper.agency.AgencyBillMapper;
import com.fg.cloud.manager.mapper.order.OrderInfoMapper;
import com.fg.cloud.manager.service.BaseServiceImpl;
import com.fg.cloud.manager.service.agency.AgencyBillService;

/**
 * Description:经销商账单流水serviceImpl
 * 
 * @author shaoqiping
 * @date 2017年8月21日上午11:09:04
 */
@Service
public class AgencyBillServiceImpl extends BaseServiceImpl implements AgencyBillService {

	@Autowired
	private AgencyBillMapper billMapper;

	@Autowired
	private AgencyAccountMapper agencyAccountMapper;

	@Autowired
	private OrderInfoMapper orderInfoMapper;

	@Override
	protected <T extends BaseEntity> BaseMapper getBaseMapper() {
		return billMapper;
	}

	@Override
	public void findList(PageUtils<AgencyBillVo> pageinfo) {
		long total = billMapper.filterCount(pageinfo.getCondition());
		pageinfo.setTotal(total);
		if (total > 0) {
			pageinfo.setData(billMapper.findList(pageinfo));
		} else {
			pageinfo.setData(new ArrayList<AgencyBillVo>());
		}
	}

	@Override
	public void highFindList(PageUtils<AgencyBillVo> pageinfo) {
		long total = billMapper.highFilterCount(pageinfo.getCondition());
		pageinfo.setTotal(total);
		if (total > 0) {
			pageinfo.setData(billMapper.highFindList(pageinfo));
		} else {
			pageinfo.setData(new ArrayList<AgencyBillVo>());
		}
	}

	@Override
	@Transactional
	public boolean confirm(AgencyBillEntity entity) {
		int temp = billMapper.updateByPrimaryKeySelective(entity);
		if (entity.getTransMode() == 4) {
			OrderInfoEntity order = new OrderInfoEntity();
			OrderInfoEntity template = orderInfoMapper.find(entity.getOrderId());
			order.setNeedPay(template.getNeedPay().subtract(entity.getConfirmAmount()));
			if (order.getNeedPay().compareTo(new BigDecimal(0)) <= 0) {
				order.setPayStatus(PayStatus.ALL);
			} else {
				order.setPayStatus(PayStatus.PORTION);
			}
			order.setId(entity.getOrderId());
			orderInfoMapper.update(order);
		}
		if (entity.getTransInfo() == AgencyBill.ORDERPAY && entity.getTransMode() == 5) {
			OrderInfoEntity order = new OrderInfoEntity();
			OrderInfoEntity template = orderInfoMapper.find(entity.getOrderId());
			order.setNeedPay(template.getNeedPay().subtract(entity.getConfirmAmount()));
			if (order.getNeedPay().compareTo(new BigDecimal(0)) <= 0) {
				order.setPayStatus(PayStatus.ALL);
			} else {
				order.setPayStatus(PayStatus.PORTION);
			}
			order.setId(entity.getOrderId());
			order.setNeedPay(null);
			orderInfoMapper.update(order);
		}
		if (entity.getTransInfo() == AgencyBill.AMOUNT_ADD && entity.getOrderId() == 0) {
			AgencyAccountEntity accountEntity = new AgencyAccountEntity();
			accountEntity.setFacId(entity.getFacId());
			accountEntity.setAgeId(entity.getAgeId());
			accountEntity.setType(AgencyAccount.CASH);
			AgencyAccountEntity template = agencyAccountMapper.selectBycondition(accountEntity);
			accountEntity.setLimitUsable(template.getLimitUsable().add(entity.getConfirmAmount()));
			accountEntity.setUpdateTime(new Date());
			accountEntity.setId(template.getId());
			agencyAccountMapper.update(accountEntity);
		}
		if (entity.getTransInfo() == AgencyBill.REPAYMENT) {
			FactoryUserVo user = (FactoryUserVo) UserUtils.getCurrentUser();
			BigDecimal amount = entity.getConfirmAmount();
			List<OrderInfoEntity> orders = new ArrayList<OrderInfoEntity>();
			List<AgencyBillEntity> flows = new ArrayList<AgencyBillEntity>();
			List<OrderPaymentEntity> needPays = orderInfoMapper.selectUnfinished(entity.getFacId(),
					entity.getAgeId());
			for (OrderPaymentEntity paymentEntity : needPays) {
				if (amount.compareTo(paymentEntity.getNeedPay()) < 0) {
					if (amount.compareTo(BigDecimal.ZERO) == 0) {
						break;
					}
					OrderInfoEntity order = new OrderInfoEntity();
					order.setPayStatus(PayStatus.PORTION);
					order.setId(paymentEntity.getOrderId());
					OrderInfoEntity orderInfo = orderInfoMapper.find(paymentEntity.getOrderId());
					order.setNeedPay(orderInfo.getNeedPay().subtract(amount));
					
					orders.add(order);

					AgencyBillEntity flow = new AgencyBillEntity();
					flow.setFacId(entity.getFacId());
					flow.setAgeId(entity.getAgeId());
					flow.setOrderId(paymentEntity.getOrderId());
					flow.setOrderNum(paymentEntity.getOrderNo());
					flow.setRunningNum(NumberUtil.getSerialNumber());
					flow.setTransTime(new Date());
					flow.setConfirmTime(new Date());
					flow.setAmount(amount);
					flow.setConfirmAmount(amount);
					flow.setStatus(AgencyBill.STATUS);
					flow.setTransId(entity.getId());
					flow.setTransInfo(AgencyBill.ORDERPAY);
					flow.setTransMode(entity.getTransMode());
					flow.setPayAccount(AgencyBill.CASH);
					flow.setCollectionAccount(entity.getCollectionAccount());
					flow.setAdmin(user.getTrueName());

					flows.add(flow);
					amount=BigDecimal.ZERO;
				} else {
					amount = amount.subtract(paymentEntity.getNeedPay());
					OrderInfoEntity order = new OrderInfoEntity();
					order.setPayStatus(PayStatus.ALL);
					order.setId(paymentEntity.getOrderId());
					order.setNeedPay(BigDecimal.ZERO);
					orders.add(order);

					AgencyBillEntity flow = new AgencyBillEntity();
					flow.setFacId(entity.getFacId());
					flow.setAgeId(entity.getAgeId());
					flow.setOrderId(paymentEntity.getOrderId());
					flow.setOrderNum(paymentEntity.getOrderNo());
					flow.setRunningNum(NumberUtil.getSerialNumber());
					flow.setTransTime(new Date());
					flow.setConfirmTime(new Date());
					flow.setAmount(paymentEntity.getNeedPay());
					flow.setConfirmAmount(paymentEntity.getNeedPay());
					flow.setStatus(AgencyBill.STATUS);
					flow.setTransId(entity.getId());
					flow.setTransInfo(AgencyBill.ORDERPAY);
					flow.setTransMode(entity.getTransMode());
					flow.setPayAccount(AgencyBill.CASH);
					flow.setCollectionAccount(entity.getCollectionAccount());
					flow.setAdmin(user.getTrueName());

					flows.add(flow);
				}
			}
			if(flows.size()>20){
				List<List<?>> flowList=splitList(flows, 20);
				for (List<?> list : flowList) {
					billMapper.insertFlows((List<AgencyBillEntity>) list);
				}
				List<List<?>> orderList=splitList(flows, 20);
				for (List<?> list : orderList) {
					orderInfoMapper.updateNeedPay((List<OrderInfoEntity>) list);
				}
			}else{
				billMapper.insertFlows(flows);
				orderInfoMapper.updateNeedPay(orders);
			}
		}
		if (entity.getTransId() != null) {
			if (entity.getTransId() != 0) {
				OrderInfoEntity order = new OrderInfoEntity();
				OrderInfoEntity template = orderInfoMapper.find(entity.getOrderId());
				order.setNeedPay(template.getNeedPay().subtract(entity.getConfirmAmount()));
				if (order.getNeedPay().compareTo(new BigDecimal(0)) <= 0) {
					order.setPayStatus(PayStatus.ALL);
				} else {
					order.setPayStatus(PayStatus.PORTION);
				}
				order.setId(entity.getOrderId());
				orderInfoMapper.update(order);
				entity.setId(entity.getTransId());
				entity.setConfirmAmount(entity.getConfirmAmount());
				temp += billMapper.updateByPrimaryKeySelective(entity);
			}
		}
		return temp > 0;
	}

	@Override
	@Transactional
	public boolean deleteUnconfirmed(Long id, Long ageId) {
		billMapper.deleteStatementPays(id);
		return billMapper.deleteUnconfirmed(id, ageId) > 0;
	}

	@Override
	@Transactional
	public boolean insertSelective(AgencyBillEntity entity, boolean temp) throws ServiceException {
		if (entity.getTransInfo() == AgencyBill.ORDERPAY) {
			AgencyAccountEntity accountEntity = new AgencyAccountEntity();
			accountEntity.setFacId(entity.getFacId());
			accountEntity.setAgeId(entity.getAgeId());
			if (entity.getPayAccount() == 1) {
				accountEntity.setType(AgencyAccount.CASH);
			} else {
				accountEntity.setType(AgencyAccount.CREDIT);
			}
			AgencyAccountEntity template = agencyAccountMapper.selectBycondition(accountEntity);
			BigDecimal amount = template.getLimitUsable().subtract(entity.getAmount());
			if (amount.compareTo(BigDecimal.ZERO) < 0) {
				throw new ServiceException(StatusCode.OPERATIONERROR, "账户余额不足，无法完成支付");
			}
			accountEntity.setLimitUsable(amount);
			accountEntity.setUpdateTime(new Date());
			accountEntity.setId(template.getId());
			agencyAccountMapper.update(accountEntity);
		}
		// 处理订单状态反写，订单是是否自动收款确认
		if (!temp) {
			if (entity.getTransMode() == AgencyBill.CONFIRM2) {
				entity.setConfirmTime(new Date());
				entity.setConfirmAmount(entity.getAmount());
				entity.setStatus(AgencyBill.STATUS);

				OrderInfoEntity order = new OrderInfoEntity();
				OrderInfoEntity template = orderInfoMapper.find(entity.getOrderId());
				order.setNeedPay(template.getNeedPay().subtract(entity.getConfirmAmount()));
				if (order.getNeedPay().compareTo(new BigDecimal(0)) <= 0) {
					order.setPayStatus(PayStatus.ALL);
				} else {
					order.setPayStatus(PayStatus.PORTION);
				}
				order.setId(entity.getOrderId());
				orderInfoMapper.update(order);
			}
			if(entity.getPayAccount()==2){
				OrderInfoEntity order = new OrderInfoEntity();
				order.setId(entity.getOrderId());
				order.setPayStatus(PayStatus.WAIT);
				orderInfoMapper.update(order);
			}
		} else { // 若为手工确认收款，则将订单付款状态变更为待确认
			OrderInfoEntity order = new OrderInfoEntity();
			order.setId(entity.getOrderId());
			order.setPayStatus(PayStatus.WAIT);
			orderInfoMapper.update(order);
		}
		// 编码规则
		entity.setRunningNum(NumberUtil.getSerialNumber());
		return billMapper.insert(entity) > 0;
	}

	@Override
	@Transactional
	public boolean insert(AgencyBillEntity billEntity, boolean flag) {
		if (!flag) {
			if (billEntity.getTransMode() <= AgencyBill.CONFIRM) {
				AgencyUserVo user = (AgencyUserVo) UserUtils.getCurrentUser();
				AgencyAccountEntity accountEntity = new AgencyAccountEntity();
				accountEntity.setFacId(billEntity.getFacId());
				accountEntity.setAgeId(billEntity.getAgeId());
				if (billEntity.getTransInfo() == AgencyBill.AMOUNT_ADD) {// 充值时不需要确认
					accountEntity.setType(AgencyAccount.CASH);
					AgencyAccountEntity template = agencyAccountMapper.selectBycondition(accountEntity);
					accountEntity.setLimitUsable(template.getLimitUsable().add(billEntity.getConfirmAmount()));
					accountEntity.setUpdateTime(new Date());
					accountEntity.setId(template.getId());
					accountEntity.setUpdater(user.getId());
					agencyAccountMapper.update(accountEntity);
				}
				if (billEntity.getTransInfo() == AgencyBill.REPAYMENT) {// 信用还款时不需要确认
					accountEntity.setType(AgencyAccount.CREDIT);
					accountEntity = agencyAccountMapper.selectBycondition(accountEntity);
					accountEntity.setType(null);
					accountEntity.setLimitStatus(null);
					accountEntity.setLimitMoney(null);
					accountEntity.setLimitUsable(accountEntity.getLimitUsable().add(billEntity.getConfirmAmount()));
					accountEntity.setUpdater(user.getId());
					agencyAccountMapper.update(accountEntity);
				}
			}
		}
		// 编码规则
		billEntity.setRunningNum(NumberUtil.getSerialNumber());
		return billMapper.insert(billEntity) > 0;
	}

	@Override
	@Transactional
	public boolean insertDouble(AgencyBillEntity entity, boolean temp) {
		// 处理订单状态反写，订单是是否自动收款确认
		if (!temp) {
			if (entity.getTransMode() <= AgencyBill.CONFIRM) {
				entity.setConfirmTime(new Date());
				entity.setConfirmAmount(entity.getAmount());
				entity.setStatus(AgencyBill.STATUS);

				OrderInfoEntity order = new OrderInfoEntity();
				OrderInfoEntity template = orderInfoMapper.find(entity.getOrderId());
				order.setNeedPay(template.getNeedPay().subtract(entity.getConfirmAmount()));
				if (order.getNeedPay().compareTo(new BigDecimal(0)) <= 0) {
					order.setPayStatus(PayStatus.ALL);
				} else {
					order.setPayStatus(PayStatus.PORTION);
				}
				order.setId(entity.getOrderId());
				orderInfoMapper.update(order);
			}else{
				OrderInfoEntity order = new OrderInfoEntity();
				order.setId(entity.getOrderId());
				order.setPayStatus(PayStatus.WAIT);
				orderInfoMapper.update(order);
			}
		} else { // 若为手工确认收款，则将订单付款状态变更为待确认
			OrderInfoEntity order = new OrderInfoEntity();
			order.setId(entity.getOrderId());
			order.setPayStatus(PayStatus.WAIT);
			orderInfoMapper.update(order);
		}
		AgencyBillEntity entity2 = new AgencyBillEntity();
		BeanUtils.copyProperties(entity, entity2);// copy属性
		// entity2.setOrderId(null);
		// entity2.setOrderNum(null);//mark 充值暂时加上订单编码
		entity2.setPayAccount(null);
		// entity2.setCollectionAccount(null);
		entity2.setUploadPic(null);
		entity2.setTransInfo(AgencyBill.AMOUNT_ADD);
		// 编码规则
		entity2.setRunningNum(NumberUtil.getSerialNumber());
		billMapper.insert(entity2);
		entity.setTransId(entity2.getId());
		// 编码规则
		// entity.setCollectionAccount(null);
		entity.setRunningNum(NumberUtil.getSerialNumber());
		return billMapper.insert(entity) > 0;
	}

	@Override
	public AgencyBillEntity selectToCheck(Long id) {
		return billMapper.find(id);
	}

	@Override
	public List<OrderPaymentEntity> findUnfinished(Long facId, Long ageId) {
		return orderInfoMapper.selectUnfinished(facId, ageId);
	}

	@Override
	@Transactional
	public boolean orderPayment(AgencyBillEntity billEntity, boolean confirm) {
		billEntity.setRunningNum(NumberUtil.getSerialNumber());
		int flag = insert(billEntity);
		if (confirm) {
			BigDecimal amount = billEntity.getAmount();
			List<OrderInfoEntity> orders = new ArrayList<OrderInfoEntity>();
			List<AgencyBillEntity> flows = new ArrayList<AgencyBillEntity>();
			List<OrderPaymentEntity> needPays = orderInfoMapper.selectUnfinished(billEntity.getFacId(),
					billEntity.getAgeId());
			for (OrderPaymentEntity paymentEntity : needPays) {
				if (amount.compareTo(paymentEntity.getNeedPay()) < 0) {
					if (amount.compareTo(BigDecimal.ZERO) == 0) {
						break;
					}
					OrderInfoEntity temp = new OrderInfoEntity();
					temp.setPayStatus(PayStatus.PORTION);
					temp.setId(paymentEntity.getOrderId());
					OrderInfoEntity orderInfo = orderInfoMapper.find(paymentEntity.getOrderId());
					temp.setNeedPay(orderInfo.getNeedPay().subtract(amount));
					
					orders.add(temp);

					AgencyBillEntity flow = new AgencyBillEntity();
					flow.setFacId(billEntity.getFacId());
					flow.setAgeId(billEntity.getAgeId());
					flow.setOrderId(paymentEntity.getOrderId());
					flow.setOrderNum(paymentEntity.getOrderNo());
					flow.setRunningNum(NumberUtil.getSerialNumber());
					flow.setTransTime(new Date());
					flow.setConfirmTime(new Date());
					flow.setAmount(amount);
					flow.setConfirmAmount(amount);
					flow.setStatus(AgencyBill.STATUS);
					flow.setTransId(billEntity.getId());
					flow.setTransInfo(AgencyBill.ORDERPAY);
					flow.setTransMode(billEntity.getTransMode());
					flow.setPayAccount(AgencyBill.CASH);
					flow.setCollectionAccount(billEntity.getCollectionAccount());

					flows.add(flow);
					amount=BigDecimal.ZERO;
				} else {
					amount = amount.subtract(paymentEntity.getNeedPay());
					OrderInfoEntity temp = new OrderInfoEntity();
					temp.setPayStatus(PayStatus.ALL);
					temp.setId(paymentEntity.getOrderId());
					temp.setNeedPay(BigDecimal.ZERO);
					orders.add(temp);

					AgencyBillEntity flow = new AgencyBillEntity();
					flow.setFacId(billEntity.getFacId());
					flow.setAgeId(billEntity.getAgeId());
					flow.setOrderId(paymentEntity.getOrderId());
					flow.setOrderNum(paymentEntity.getOrderNo());
					flow.setRunningNum(NumberUtil.getSerialNumber());
					flow.setTransTime(new Date());
					flow.setConfirmTime(new Date());
					flow.setAmount(paymentEntity.getNeedPay());
					flow.setConfirmAmount(paymentEntity.getNeedPay());
					flow.setStatus(AgencyBill.STATUS);
					flow.setTransId(billEntity.getId());
					flow.setTransInfo(AgencyBill.ORDERPAY);
					flow.setTransMode(billEntity.getTransMode());
					flow.setPayAccount(AgencyBill.CASH);
					flow.setCollectionAccount(billEntity.getCollectionAccount());

					flows.add(flow);
				}
			}
			if(flows.size()>20){
				List<List<?>> flowList=splitList(flows, 20);
				for (List<?> list : flowList) {
					billMapper.insertFlows((List<AgencyBillEntity>) list);
				}
				List<List<?>> orderList=splitList(flows, 20);
				for (List<?> list : orderList) {
					orderInfoMapper.updateNeedPay((List<OrderInfoEntity>) list);
				}
			}else{
				billMapper.insertFlows(flows);
				orderInfoMapper.updateNeedPay(orders);
			}
		}
		return flag > 0;
	}
	
	/**
	  * Description:集合拆分方法
	  * @param list
	  * @param len
	  * @return
	  * @author shaoqiping
	  * @date 2017年10月19日下午2:45:14
	*/
	public static List<List<?>> splitList(List<?> list, int len) {
		if (list == null || list.size() == 0 || len < 1) {
			return null;
		}
		List<List<?>> result = new ArrayList<List<?>>();
		int size = list.size();
		int count = (size + len - 1) / len;
		for (int i = 0; i < count; i++) {
		List<?> subList = list.subList(i * len, ((i + 1) * len > size ? size : len * (i + 1)));
		result.add(subList);
		}
		return result;
	}
	
	@Override
	public void findOrderAmount(PageUtils<AgencyBillEntity> pageinfo) {
		long total = billMapper.selectOrderPaymentCount(pageinfo.getCondition());
		pageinfo.setTotal(total);
		if (total > 0) {
			pageinfo.setData(billMapper.selectOrderPaymentList(pageinfo));
		} else {
			pageinfo.setData(new ArrayList<AgencyBillEntity>());
		}
	}

	@Override
	public Map<String, Object> findListWeChat(PageUtils<AgencyBillVo> pageinfo) {
		long total = billMapper.filterCount(pageinfo.getCondition());
		if (total > 0) {
			List<AgencyBillVo> temp = billMapper.findList(pageinfo);
			List<AgencyBillWeChatEntity> list = new ArrayList<>();
			SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月");
			String time = "";
			int flag1 = 0;
			int flag2 = 0;
			for (int i = 0; i < temp.size(); i++) {
				if (time.equals("")) {
					time = format.format(temp.get(i).getTransTime());
				} else {
					if (!time.equals(format.format(temp.get(i).getTransTime()))) {
						List<AgencyBillVo> data = new ArrayList<AgencyBillVo>();
						if (flag1 > 0) {
							flag1 = flag2;
						} else {
							flag1 = 0;
						}
						flag2 = i;
						data = temp.subList(flag1, flag2);
						AgencyBillWeChatEntity entity = new AgencyBillWeChatEntity();
						if (time.equals(format.format(new Date()))) {
							entity.setMonth("本月");
						} else {
							entity.setMonth(time);
						}
						entity.setFlows(data);
						list.add(entity);
						time = format.format(temp.get(i).getTransTime());
					}
					if (i == temp.size() - 1) {
						flag1 = flag2;
						List<AgencyBillVo> data = new ArrayList<AgencyBillVo>();
						data = temp.subList(flag1, i + 1);
						AgencyBillWeChatEntity entity = new AgencyBillWeChatEntity();
						if (time.equals(format.format(new Date()))) {
							entity.setMonth("本月");
						} else {
							entity.setMonth(time);
						}
						if (data == null || data.size() == 0) {
							data = new ArrayList<AgencyBillVo>();
							entity.setMonth(null);
						}
						entity.setFlows(data);
						entity.setTotal(total);
						list.add(entity);
					}
				}
			}
			Map<String, Object> map = new HashMap<>();
			map.put("total", total);
			map.put("data", list);
			return map;
		} else {
			return null;
		}
	}

	@Override
	public List<AgencyBillEntity> findOrderPayment(Long orderId) {
		return billMapper.selectOrderPayment(orderId);
	}
}
